package com.example.java_gobang.game;

import com.example.java_gobang.model.User;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.LinkedList;
import java.util.Queue;

@Slf4j
@Component
public class Matcher {
    //三个用于匹配的 队列
    private Queue<User> normalQueue = new LinkedList<>();  // 2000 以下
    private Queue<User> highQueue = new LinkedList<>(); // 2000 - 3000
    private Queue<User> veryHighQueue = new LinkedList<>(); // 3000 以上

    @Autowired
    private OnlineUserManager onlineUserManager;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private RoomManager roomManager;

    //开始匹配时，将用户加入队列
    public void add(User user) {
        Integer score = user.getScore();
        if (score < 2000) {
            synchronized (normalQueue) {
                normalQueue.offer(user);
                normalQueue.notify();
            }
            log.info(user.getUserName() + "加到 noraml");
        } else if (score >= 2000 && score < 3000) {
            synchronized (highQueue) {
                highQueue.offer(user);
                highQueue.notify();
            }
            log.info(user.getUserName() + "加到 high");
        } else{
            synchronized (veryHighQueue) {
                veryHighQueue.offer(user);
                veryHighQueue.notify();
            }
            log.info(user.getUserName() + "加到 veryHigh");
        }
    }


    //停止匹配时，从队列中移除
    public void remove(User user) {
        Integer score = user.getScore();
        if (score < 2000) {
            synchronized (normalQueue) {
                normalQueue.remove(user);
            }
            log.info(user.getUserName() + "从 normal 移除");
        } else if (score >= 2000 && score < 3000) {
            synchronized (highQueue) {
                highQueue.remove(user);
            }
            log.info(user.getUserName() + "从 high 移除");
        } else{
            synchronized (veryHighQueue) {
                veryHighQueue.remove(user);
            }
            log.info(user.getUserName() + "从 veryHigh 移除");
        }
    }

    public Matcher() {
        Thread thread1 = new Thread() {
            @Override
            public void run() {
                while (true) {
                    handlerMatch(normalQueue);
                }
            }
        };
        thread1.start();

        Thread thread2 = new Thread() {
            @Override
            public void run() {
                while (true) {
                    handlerMatch(highQueue);
                }
            }
        };
        thread2.start();

        Thread thread3 = new Thread() {
            @Override
            public void run() {
                while (true) {
                    handlerMatch(veryHighQueue);
                }

            }
        };
        thread3.start();


    }

    private void handlerMatch(Queue<User> mathQueue) {
        synchronized (mathQueue) {
            try {
                // 1. 检测是否符合匹配要求
                while (mathQueue.size() < 2) {
                    //数量不够休眠
                    mathQueue.wait();

                }

                //2. 从队列中取出 两个玩家
                User player1 = mathQueue.poll();
                User player2 = mathQueue.poll();
                log.info("【handlerMatch】玩家1：" + player1 + "; 玩家2：" + player2);

                //3. 获取玩家的 session 对话
                //以便告诉玩家，匹配到了对手
                WebSocketSession session1 = onlineUserManager.getFromGameHall(player1.getUserId());
                WebSocketSession session2 = onlineUserManager.getFromGameHall(player2.getUserId());

                // 理论上，匹配到达玩家一定是在线的（MatchAPI 中进行了 关闭处理）
                // 但这里仍再判定一次
                if (session1 == null) {
                    mathQueue.offer(player2);
                    return;
                }
                if (session2 == null) {
                    mathQueue.offer(player1);
                    return;
                }

                //理论上，不会匹配到自己, 对重开进行了处理，这里再判断
                if (session1 == session2) {
                    mathQueue.offer(player1);
                    return;
                }


                //4. 将两个玩家拉到对战厅
                Room room = new Room();
                roomManager.add(room,player1.getUserId(), player2.getUserId());


                //5. 给两个玩家发送消息,告诉玩家匹配到了对手
                MatchResponse response = new MatchResponse();
                response.setOk(true);
                response.setMessage("matchSuccess");
                String json = objectMapper.writeValueAsString(response);

                session1.sendMessage(new TextMessage(json));

                session2.sendMessage(new TextMessage(json));

            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}
